package jmine.tec.executionlog.dao;

import java.util.List;

import jmine.tec.executionlog.domain.ExecutionLog;
import jmine.tec.executionlog.domain.ExecutionLogItem;
import jmine.tec.executionlog.domain.enumx.ExecutionItemStatus;

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import bancosys.tec.persist.dao.BaseDAO;
import bancosys.tec.persist.dataset.HibernateRandomAccessResultSet;
import bancosys.tec.persist.hibernate.RestrictionsUtils;

/**
 * DAO de Item de Log de execucao de Data Digester.
 * 
 * @author Marcio Ribeiro (mmr)
 * @created Jun 19, 2008
 */
public class ExecutionLogItemDAO extends BaseDAO<ExecutionLogItem> {

    /**
     * Sobrecarga do método {@link BaseDAO#findByExample(bancosys.tec.persist.Persistable, boolean, String...)}
     * 
     * @param executionLogItem entidade a ser usada como exemplo
     * @param literal indica se a query deve ser literal ou deve utilizar <code>ignoreCase</code> e <code>like</code>.
     * @param excludeProperties as propriedades que devem ser ignoradas no exemplo.
     * @return uma lista de entidades.
     * @deprecated we are encouraging people to not use findByExample and family
     */
    @Override
    public List<ExecutionLogItem> findByExample(ExecutionLogItem executionLogItem, boolean literal, String... excludeProperties) {
        Criteria criteria = this.createCriteria();

        if (executionLogItem.getStatus() == null) {
            criteria.add(super.mountExample(executionLogItem, literal, "status"));
        } else {
            criteria.add(super.mountExample(executionLogItem, literal));
        }

        this.addExampleCriteria(criteria, literal, executionLogItem.getExecutionLog(), "executionLog");

        return this.executeQuery(criteria);
    }

    /**
     * Procura os execution log item associados ao executionLog passado como parametro
     * 
     * @param executionLog executionLog
     * @param status status que o executionLogItem foi concluido (opcional)
     * @return os ExecutionLogItem associado ao executionLog passado como parametro
     */
    public List<ExecutionLogItem> findByExecutionLogStatus(ExecutionLog executionLog, ExecutionItemStatus status) {
        Criteria criteria = this.createCriteria();
        RestrictionsUtils.addRestrictionEqId(criteria, "executionLog.id", executionLog);
        RestrictionsUtils.addRestrictionEq(criteria, "status", status);
        criteria.addOrder(Order.asc("id"));
        return this.executeQuery(criteria);
    }

    /**
     * Busca todos os items deste execution log através de um HibernateRandomAccessResultSet
     * 
     * @param executionLog executionLog
     * @param status status que o executionLogItem foi concluido (opcional)
     * @return HibernateRandomAccessResultSet de ExecutionLogItem
     */
    public HibernateRandomAccessResultSet<ExecutionLogItem> findByExecutionLog(ExecutionLog executionLog, ExecutionItemStatus status) {
        Criteria criteria = this.createCriteria();
        RestrictionsUtils.addRestrictionEqId(criteria, "executionLog.id", executionLog);
        RestrictionsUtils.addRestrictionEq(criteria, "status", status);
        criteria.addOrder(Order.asc("id"));
        return new HibernateRandomAccessResultSet<ExecutionLogItem>(this.getSession(), criteria);
    }

    /**
     * Encontra a lista de ExecutionLogItens entes os dois informados, inclusive
     * 
     * @param from from
     * @param to to
     * @return List de ExecutionLogItem
     */
    public List<ExecutionLogItem> findItemsBetween(ExecutionLogItem from, ExecutionLogItem to) {
        Criteria criteria = this.createCriteria();
        RestrictionsUtils.addRestrictionEqId(criteria, "executionLog.id", from.getExecutionLog());
        RestrictionsUtils.addRestrictionGe(criteria, "id", from.getId());
        RestrictionsUtils.addRestrictionLe(criteria, "id", to.getId());
        criteria.addOrder(Order.asc("id"));
        return this.executeQuery(criteria);
    }

    /**
     * Contagem de itens para a execucao passada.
     * 
     * @param executionLog a execucao.
     * @return contagem de itens para a execucao passada.
     */
    public int countByExecutionLog(ExecutionLog executionLog) {
        Criteria crit = this.createCriteria();
        crit.add(Restrictions.eq("executionLog", executionLog));
        crit.setProjection(Projections.rowCount());
        return ((Integer) crit.list().get(0)).intValue();
    }

    /**
     * Contagem de itens para a execucao passada, com um dado status.
     * 
     * @param executionLog a execucao.
     * @param status o status do item executado.
     * @return contagem de itens para a execucao e status passada.
     */
    public int countByExecutionLogStatus(ExecutionLog executionLog, ExecutionItemStatus status) {
        Criteria crit = this.createCriteria();
        RestrictionsUtils.addRestrictionEqId(crit, "executionLog.id", executionLog);
        RestrictionsUtils.addRestrictionEq(crit, "status", status);
        crit.setProjection(Projections.rowCount());
        return ((Integer) crit.list().get(0)).intValue();
    }

}
